package com.studyhub.message.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.studyhub.api.message.MessageResult;
import com.studyhub.api.message.entity.NoticeMessageEntity;
import com.studyhub.api.message.enums.MessageCodeEnum;
import com.studyhub.api.message.enums.MessageTypeEnum;
import com.studyhub.api.message.model.MessageInfo;
import com.studyhub.api.message.vo.NoticeMessagePage;
import com.studyhub.api.message.vo.NoticeMessageQueryVO;
import com.studyhub.api.message.vo.NoticeMessageStatsVO;
import com.studyhub.core.enums.ClientIdEnum;
import com.studyhub.message.interceptor.MyWebSocketHandler;
import com.studyhub.message.mapper.NoticeMessageMapper;
import com.studyhub.message.service.INoticeMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @Description 通知消息Service实现类
 * @Author YWF
 * @Version 1.0.0
 * @Date 2025/9/26 11:00
 */
@Slf4j
@Service
public class NoticeMessageServiceImpl extends ServiceImpl<NoticeMessageMapper, NoticeMessageEntity> 
        implements INoticeMessageService {
    
    @Autowired
    private NoticeMessageMapper noticeMessageMapper;
    
    @Autowired
    private MyWebSocketHandler webSocketHandler;
    
    @Override
    public IPage<NoticeMessagePage> pageNoticeMessages(NoticeMessageQueryVO queryVO, Long userId) {
        Page<NoticeMessagePage> page = new Page<>(queryVO.getPageNum(), queryVO.getPageSize());
        return noticeMessageMapper.selectNoticeMessagePage(page, queryVO, userId);
    }
    
    @Override
    public NoticeMessageStatsVO getNoticeMessageStats(Long userId) {
        return noticeMessageMapper.selectNoticeMessageStats(userId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean sendNoticeMessage(NoticeMessageEntity message) {
        try {
            log.info("开始发送通知消息，用户ID: {}, 消息类型: {}, 标题: {}", 
                    message.getUserId(), message.getMessageType(), message.getMessageTitle());
            
            // 设置创建时间
            if (message.getCreatedAt() == null) {
                message.setCreatedAt(LocalDateTime.now());
            }
            if (message.getUpdatedAt() == null) {
                message.setUpdatedAt(LocalDateTime.now());
            }
            
            // 保存到数据库
            boolean saved = this.save(message);
            
            if (saved) {
                log.info("通知消息保存成功，消息ID: {}", message.getId());
                
                // 如果是紧急消息(messageType = 1)，通过WebSocket实时推送
                if (isUrgentMessage(message)) {
                    log.info("检测到紧急消息，开始WebSocket实时推送，用户ID: {}", message.getUserId());
                    boolean pushResult = sendWebSocketNotification(message);
                    if (pushResult) {
                        log.info("紧急消息WebSocket推送成功，用户ID: {}", message.getUserId());
                    } else {
                        log.warn("紧急消息WebSocket推送失败，用户ID: {}", message.getUserId());
                    }
                } else {
                    log.debug("普通消息，不进行WebSocket推送，用户ID: {}", message.getUserId());
                }
            } else {
                log.error("通知消息保存失败，用户ID: {}", message.getUserId());
            }
            
            return saved;
        } catch (Exception e) {
            log.error("发送通知消息失败，用户ID: {}, 错误信息: {}", message.getUserId(), e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchSendNoticeMessages(List<NoticeMessageEntity> messages) {
        int successCount = 0;
        for (NoticeMessageEntity message : messages) {
            if (sendNoticeMessage(message)) {
                successCount++;
            }
        }
        return successCount;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAsRead(Long messageId, Long userId) {
        NoticeMessageEntity message = new NoticeMessageEntity();
        message.setId(messageId);
        message.setRead(true);
        message.setUpdatedAt(LocalDateTime.now());
        
        QueryWrapper<NoticeMessageEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("id", messageId)
               .eq("user_id", userId);
        
        return this.update(message, wrapper);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchMarkAsRead(List<Long> messageIds, Long userId) {
        if (messageIds == null || messageIds.isEmpty()) {
            return 0;
        }
        return noticeMessageMapper.batchMarkAsRead(messageIds, userId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int markAllAsRead(Long userId) {
        return noticeMessageMapper.markAllAsRead(userId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteMessages(List<Long> messageIds, Long userId) {
        if (messageIds == null || messageIds.isEmpty()) {
            return 0;
        }
        return noticeMessageMapper.deleteByIds(messageIds, userId);
    }
    
    @Override
    public long getUnreadCount(Long userId) {
        QueryWrapper<NoticeMessageEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId)
               .eq("isRead", false)
               .and(w -> w.eq("status", false).or().isNull("status"));
        
        return this.count(wrapper);
    }
    
    /**
     * 判断是否为紧急消息
     *
     * @param message 消息实体
     * @return true表示紧急消息，false表示普通消息
     */
    private boolean isUrgentMessage(NoticeMessageEntity message) {
        return message.getMessageType() != null && message.getMessageType().equals(1);
    }
    
    /**
     * 通过WebSocket发送实时通知
     *
     * @param message 消息实体
     * @return 推送结果
     */
    private boolean sendWebSocketNotification(NoticeMessageEntity message) {
        try {
            log.debug("构建WebSocket消息，用户ID: {}, 消息类型: {}", message.getUserId(), message.getMessageType());
            
            // 构建WebSocket消息
            MessageInfo messageInfo = new MessageInfo();
            messageInfo.setUserId(message.getUserId().intValue());
            messageInfo.setClientId(ClientIdEnum.EXAM_APP);
            messageInfo.setType(MessageTypeEnum.NOTICE_MESSAGE);
            messageInfo.setTitle(message.getMessageTitle());
            messageInfo.setIntroduce(message.getMessageContent());
            messageInfo.setCreatedAt(message.getCreatedAt());
            
            MessageResult messageResult = new MessageResult();
            messageResult.setInfo(messageInfo);
            messageResult.setCode(MessageCodeEnum.NOTICE_MESSAGE);
            
            // 发送WebSocket消息
            boolean result = webSocketHandler.sendMessage(messageResult);
            if (result) {
                log.info("WebSocket通知发送成功，用户ID: {}, 消息标题: {}", 
                        message.getUserId(), message.getMessageTitle());
            } else {
                log.warn("WebSocket通知发送失败，可能用户不在线，用户ID: {}", message.getUserId());
            }
            return result;
        } catch (Exception e) {
            log.error("发送WebSocket通知异常，用户ID: {}, 错误信息: {}", 
                    message.getUserId(), e.getMessage(), e);
            return false;
        }
    }
}